<?php

class base_application_imgbundle_factory {

    private $app_id;

    private $directory;

    private $output;

    private $files = array();

    private $match;

    private $spriteinfo = array();

    private $position = 0;

    function __construct() {
        $this->reset();
    }
 // End Function
    public function set_app($app_id) {
        $this->app_id = $app_id;
        if ($this->_parse_dirctory()) {
            return $this;
        } else {
            return false;
        }
    }
 // End Function
    public function set_directory($directory) {
        $this->directory = $directory;
        if ($this->_parse_dirctory()) {
            return $this;
        } else {
            return false;
        }
    }
 // End Function
    public function set_output($output) {
        $this->output = $output;
        return $this;
    }
 // End Function
    public function set_file($file) {
        $this->files[] = $file;
        return $this;
    }
 // End Function
    public function set_files(array $files) {
        $this->files = $files;
        return $this;
    }
 // End Function
    public function reset() {
        $this->app_id = null;
        $this->directory = 'bundle';
        $this->output = '';
        $this->files = array();
        $this->match = '/^([a-z0-9\-_]+)\.(jpg|jpeg|jpe|gif)$/i';
        $this->spriteinfo = array();
        $this->position = 0;
        return $this;
    }
 // End Function
    private function _parse_dirctory() {
        if (! $this->app_id)
            return false;
        $this->files = array();
        $dir = realpath(app::get($this->app_id)->res_dir . '/' . $this->directory);
        $handle = opendir($dir);
        if ($handle) {
            while (($file = readdir($handle)) !== false) {
                if (in_array($file, array(
                    '.',
                    '..'
                )))
                    continue;
                if (preg_match($this->match, $file, $matches)) {
                    $this->files[] = $dir . '/' . $file;
                }
            }
        }
        return true;
    }
 // End Function
    public function create() {
        if (! is_callable('imagecreatefromjpeg') || ! is_callable('imagecreatefrompng') || ! is_callable('imagecreatefromgif')) {
            return array();
        } // todo:GD库需要支持jpeg,png,gif格式
        if (is_callable('imagecreatetruecolor')) {
            try {
                $image = imagecreatetruecolor(100, 200);
                imagedestroy($image);
                $flag = true;
            } catch (Exception $e) {
                $flag = false;
            }
        } else {
            $flag = false;
        } // todo:
        if ($flag && defined('PUBLIC_DIR')) {
            $output_dir = PUBLIC_DIR . '/imgbundle';
            if (! is_dir($output_dir)) {
                mkdir($output_dir, 0755, true);
            }
            $filename = str_replace('\\', '/', realpath($output_dir)) . '/' . $this->output;
            foreach ($this->files as $file) {
                $file = str_replace('\\', '/', $file);
                $orginfo = getimagesize($file);
                if ($image == null) {
                    $image = $this->_create_image($file);
                } else {
                    $image = $this->_create($filename, $file);
                }
                if ($image && $this->_write($image, $filename)) {
                    $imageinfo = getimagesize($filename);
                    $this->spriteinfo['info'][substr($file, strlen(realpath(app::get($this->app_id)->res_dir) . '/'))] = array(
                        $this->position * - 1,
                        $orginfo[0],
                        $imageinfo[1] - $this->position
                    );
                    $this->position = $imageinfo[1];
                }
            }
            $this->spriteinfo['mtime'] = time();
            $this->spriteinfo['bundleimg'] = substr($filename, strlen(realpath(ROOT_DIR)) + 1);
            return $this->spriteinfo;
        } else {
            return array();
        }
    }
 // End Function
    private function _create($file1, $file2) {
        $image1 = $this->_create_image($file1);
        if (! $image1)
            return false;
        $image2 = $this->_create_image($file2);
        if (! $image2)
            return false;
        
        $imageWidth1 = imagesx($image1);
        $imageWidth2 = imagesx($image2);
        
        $imageHeight1 = imagesy($image1);
        $imageHeight2 = imagesy($image2);
        
        $width = ($imageWidth1 > $imageWidth2 ? $imageWidth1 : $imageWidth2);
        $height = $imageHeight1 + $imageHeight2;
        
        $image = imagecreatetruecolor($width, $height);
        $bgcolor = ImageColorAllocate($image, 0, 0, 0);
        $bgcolor = ImageColorTransparent($image, $bgcolor);
        
        if (! imagecopymerge($image, $image1, 0, 0, 0, 0, $imageWidth1, $imageHeight1, 100))
            return false;
        if (! imagecopymerge($image, $image2, 0, $imageHeight1, 0, 0, $imageWidth2, $imageHeight2, 100))
            return false;
        
        imagedestroy($image1);
        imagedestroy($image2);
        
        return $image;
    }
 // End Function
    private function _create_image($filename) {
        if (! is_readable($filename))
            return false;
        $info = getimagesize($filename);
        switch ($info[2]) {
            case 2:
                try {
                    return imagecreatefromjpeg($filename);
                } catch (Exception $e) {
                    return false;
                }
            
            case 3:
                try {
                    return imagecreatefrompng($filename);
                } catch (Exception $e) {
                    return false;
                }
            
            case 1:
                try {
                    return imagecreatefromgif($filename);
                } catch (Exception $e) {
                    return false;
                }
            
            default:
                return false;
        }
        
        return false;
    }
 // End Function
    function _write($image, $filename) {
        $function = 'image' . substr($this->output, strrpos($this->output, '.') + 1);
        
        if (file_exists($filename) && ! is_writable($filename)) {
            return false;
        }
        if (function_exists($function)) {
            $res = $function($image, $filename);
        } else {
            $res = false;
        }
        imagedestroy($image);
        return $res;
    }
}//End Class